﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Drawing;

namespace DDD {
    public static class ImageWriter {

        private static float Clamp (float min, float max, float value) {
            return Math.Max (min, Math.Min (max, value));
        }

        /// <summary>
        /// 指定の画像データをPNGファイルに保存します。
        /// </summary>
        /// <remarks>
        /// この関数はデバッグ用です。
        /// 何となくそれっぽい画像を出力しますがフォーマットによっては突拍子もない画像になります。
        /// HDRに対応したトーンマッピングは未実装です。将来的には何とかします。
        /// デプスコンポーネントは奥に行くほど白くなるように出力しています。
        /// </remarks>
        /// <param name="name">ファイル名</param>
        /// <param name="img">画像</param>
        public static void Save<T> (string name, Image2D<T> img) where T : struct {
            if (name == null || name == "") {
                throw new ArgumentNullException ("Name is null or empty");
            }
            var width = img.Width;
            var height = img.Height;
            var cpp = img.Cpp;
            var format = img.PixelFormat;

            switch (format) {
                case PixelFormat.R8: {
                        var bitmap = new Bitmap (width, height, System.Drawing.Imaging.PixelFormat.Format24bppRgb);
                        var pixels = (img as Image2D<float>).Pixels.ToArray ();
                        for (var y = 0; y < height; y++) {
                            for (var x = 0; x < width; x++) {
                                var r = (int)Clamp (0, 255, pixels[y * width + x]*255);
                                var g = (int)Clamp (0, 255, pixels[y * width + x] * 255);
                                var b = (int)Clamp (0, 255, pixels[y * width + x] * 255);
                                bitmap.SetPixel (x, y, System.Drawing.Color.FromArgb (r, g, b));
                            }
                        }
                        bitmap.Save (name);
                        break;
                    }
                case PixelFormat.R8i: {
                        var bitmap = new Bitmap (width, height, System.Drawing.Imaging.PixelFormat.Format24bppRgb);
                        var pixels = (img as Image2D<sbyte>).Pixels.ToArray ();
                        for (var y = 0; y < height; y++) {
                            for (var x = 0; x < width; x++) {
                                var r = (int)Clamp (0, 255, pixels[y * width + x] + 128);
                                var g = (int)Clamp (0, 255, pixels[y * width + x] + 128);
                                var b = (int)Clamp (0, 255, pixels[y * width + x] + 128);
                                bitmap.SetPixel (x, y, System.Drawing.Color.FromArgb (r, g, b));
                            }
                        }
                        bitmap.Save (name);
                        break;
                    }
                case PixelFormat.R8ui: {
                        var bitmap = new Bitmap (width, height, System.Drawing.Imaging.PixelFormat.Format24bppRgb);
                        var pixels = (img as Image2D<byte>).Pixels.ToArray ();
                        for (var y = 0; y < height; y++) {
                            for (var x = 0; x < width; x++) {
                                var r = (int)Clamp (0, 255, pixels[y * width + x]);
                                var g = (int)Clamp (0, 255, pixels[y * width + x]);
                                var b = (int)Clamp (0, 255, pixels[y * width + x]);
                                bitmap.SetPixel (x, y, System.Drawing.Color.FromArgb (r,g,b));
                            }
                        }
                        bitmap.Save (name);
                        break;
                    }
                case PixelFormat.R16: {
                        var bitmap = new Bitmap (width, height, System.Drawing.Imaging.PixelFormat.Format24bppRgb);
                        var pixels = (img as Image2D<float>).Pixels.ToArray ();
                        for (var y = 0; y < height; y++) {
                            for (var x = 0; x < width; x++) {
                                var r = (int)Clamp (0, 255, pixels[y * width + x] * 255);
                                var g = (int)Clamp (0, 255, pixels[y * width + x] * 255);
                                var b = (int)Clamp (0, 255, pixels[y * width + x] * 255);
                                bitmap.SetPixel (x, y, System.Drawing.Color.FromArgb (r, g, b));
                            }
                        }
                        bitmap.Save (name);
                        break;
                    }
                case PixelFormat.R16f: {
                        var bitmap = new Bitmap (width, height, System.Drawing.Imaging.PixelFormat.Format24bppRgb);
                        var pixels = (img as Image2D<float>).Pixels.ToArray ();
                        for (var y = 0; y < height; y++) {
                            for (var x = 0; x < width; x++) {
                                var r = (int)Clamp (0, 255, pixels[y * width + x] * 255);
                                var g = (int)Clamp (0, 255, pixels[y * width + x] * 255);
                                var b = (int)Clamp (0, 255, pixels[y * width + x] * 255);
                                bitmap.SetPixel (x, y, System.Drawing.Color.FromArgb (r, g, b));
                            }
                        }
                        bitmap.Save (name);
                        break;
                    }
                case PixelFormat.R16i: {
                        var bitmap = new Bitmap (width, height, System.Drawing.Imaging.PixelFormat.Format24bppRgb);
                        var pixels = (img as Image2D<short>).Pixels.ToArray ();
                        for (var y = 0; y < height; y++) {
                            for (var x = 0; x < width; x++) {
                                var r = (int)Clamp (0, 255, (pixels[y * width + x] + 32768) / 256);
                                var g = (int)Clamp (0, 255, (pixels[y * width + x] + 32768) / 256);
                                var b = (int)Clamp (0, 255, (pixels[y * width + x] + 32768) / 256);
                                bitmap.SetPixel (x, y, System.Drawing.Color.FromArgb (r, g, b));
                            }
                        }
                        bitmap.Save (name);
                        break;
                    }
                case PixelFormat.R16ui: {
                        var bitmap = new Bitmap (width, height, System.Drawing.Imaging.PixelFormat.Format24bppRgb);
                        var pixels = (img as Image2D<ushort>).Pixels.ToArray ();
                        for (var y = 0; y < height; y++) {
                            for (var x = 0; x < width; x++) {
                                var r = (int)Clamp (0, 255, pixels[y * width + x] / 256);
                                var g = (int)Clamp (0, 255, pixels[y * width + x] / 256);
                                var b = (int)Clamp (0, 255, pixels[y * width + x] / 256);
                                bitmap.SetPixel (x, y, System.Drawing.Color.FromArgb (r, g, b));
                            }
                        }
                        bitmap.Save (name);
                        break;
                    }
                case PixelFormat.R32f: {
                        var bitmap = new Bitmap (width, height, System.Drawing.Imaging.PixelFormat.Format24bppRgb);
                        var pixels = (img as Image2D<float>).Pixels.ToArray ();
                        for (var y = 0; y < height; y++) {
                            for (var x = 0; x < width; x++) {
                                var r = (int)Clamp (0, 255, pixels[y * width + x] * 255);
                                var g = (int)Clamp (0, 255, pixels[y * width + x] * 255);
                                var b = (int)Clamp (0, 255, pixels[y * width + x] * 255);
                                bitmap.SetPixel (x, y, System.Drawing.Color.FromArgb (r,g, b));
                            }
                        }
                        bitmap.Save (name);
                        break;
                    }
                case PixelFormat.R32i: {
                        var bitmap = new Bitmap (width, height, System.Drawing.Imaging.PixelFormat.Format24bppRgb);
                        var pixels = (img as Image2D<int>).Pixels.ToArray ();
                        for (var y = 0; y < height; y++) {
                            for (var x = 0; x < width; x++) {
                                var r = (int)Clamp (0, 255, (pixels[y * width + x] + 32768) / 256);
                                var g = (int)Clamp (0, 255, (pixels[y * width + x] + 32768) / 256);
                                var b = (int)Clamp (0, 255, (pixels[y * width + x] + 32768) / 256);
                                bitmap.SetPixel (x, y, System.Drawing.Color.FromArgb (r, g, b));
                            }
                        }
                        bitmap.Save (name);
                        break;
                    }
                case PixelFormat.R32ui: {
                        var bitmap = new Bitmap (width, height, System.Drawing.Imaging.PixelFormat.Format24bppRgb);
                        var pixels = (img as Image2D<uint>).Pixels.ToArray ();
                        for (var y = 0; y < height; y++) {
                            for (var x = 0; x < width; x++) {
                                var r = (int)Clamp (0, 255, pixels[y * width + x] / 256);
                                var g = (int)Clamp (0, 255, pixels[y * width + x] / 256);
                                var b = (int)Clamp (0, 255, pixels[y * width + x] / 256);
                                bitmap.SetPixel (x, y, System.Drawing.Color.FromArgb (r, g, b));
                            }
                        }
                        bitmap.Save (name);
                        break;
                    }
                case PixelFormat.RG8: {
                        var bitmap = new Bitmap (width, height, System.Drawing.Imaging.PixelFormat.Format24bppRgb);
                        var pixels = (img as Image2D<float>).Pixels.ToArray ();
                        for (var y = 0; y < height; y++) {
                            for (var x = 0; x < width; x++) {
                                var r = (int)Clamp (0, 255, pixels[y * width + x + 0] * 255);
                                var g = (int)Clamp (0, 255, pixels[y * width + x + 1] * 255);
                                var b = (int)Clamp (0, 255, (r + g) / 2);
                                bitmap.SetPixel (x, y, System.Drawing.Color.FromArgb (r, g, b));
                            }
                        }
                        bitmap.Save (name);
                        break;
                    }
                case PixelFormat.RG8i: {
                        var bitmap = new Bitmap (width, height, System.Drawing.Imaging.PixelFormat.Format24bppRgb);
                        var pixels = (img as Image2D<sbyte>).Pixels.ToArray ();
                        for (var y = 0; y < height; y++) {
                            for (var x = 0; x < width; x++) {
                                var r = (int)Clamp (0, 255, pixels[y * width + x + 0] + 128);
                                var g = (int)Clamp (0, 255, pixels[y * width + x + 1] + 128);
                                var b = (int)Clamp (0, 255, (r + g) / 2);
                                bitmap.SetPixel (x, y, System.Drawing.Color.FromArgb (r, g, b));
                            }
                        }
                        bitmap.Save (name);
                        break;
                    }
                case PixelFormat.RG8ui: {
                        var bitmap = new Bitmap (width, height, System.Drawing.Imaging.PixelFormat.Format24bppRgb);
                        var pixels = (img as Image2D<byte>).Pixels.ToArray ();
                        for (var y = 0; y < height; y++) {
                            for (var x = 0; x < width; x++) {
                                var r = (int)Clamp (0, 255, pixels[y * width + x + 0]);
                                var g = (int)Clamp (0, 255, pixels[y * width + x + 1]);
                                var b = (int)Clamp (0, 255, (r + g) / 2);
                                bitmap.SetPixel (x, y, System.Drawing.Color.FromArgb (r, g, b));
                            }
                        }
                        bitmap.Save (name);
                        break;
                    }
                case PixelFormat.RG16: {
                        var bitmap = new Bitmap (width, height, System.Drawing.Imaging.PixelFormat.Format24bppRgb);
                        var pixels = (img as Image2D<float>).Pixels.ToArray ();
                        for (var y = 0; y < height; y++) {
                            for (var x = 0; x < width; x++) {
                                var r = (int)Clamp (0, 255, pixels[y * width + x + 0] * 255);
                                var g = (int)Clamp (0, 255, pixels[y * width + x + 1] * 255);
                                var b = (int)Clamp (0, 255, (r + g) / 2);
                                bitmap.SetPixel (x, y, System.Drawing.Color.FromArgb (r, g, b));
                            }
                        }
                        bitmap.Save (name);
                        break;
                    }
                case PixelFormat.RG16f: {
                        var bitmap = new Bitmap (width, height, System.Drawing.Imaging.PixelFormat.Format24bppRgb);
                        var pixels = (img as Image2D<float>).Pixels.ToArray ();
                        for (var y = 0; y < height; y++) {
                            for (var x = 0; x < width; x++) {
                                var r = (int)Clamp (0, 255, pixels[y * width + x + 0] * 255);
                                var g = (int)Clamp (0, 255, pixels[y * width + x + 1] * 255);
                                var b = (int)Clamp (0, 255, (r + g) / 2);
                                bitmap.SetPixel (x, y, System.Drawing.Color.FromArgb (r, g, b));
                            }
                        }
                        bitmap.Save (name);
                        break;
                    }
                case PixelFormat.RG16i: {
                        var bitmap = new Bitmap (width, height, System.Drawing.Imaging.PixelFormat.Format24bppRgb);
                        var pixels = (img as Image2D<short>).Pixels.ToArray ();
                        for (var y = 0; y < height; y++) {
                            for (var x = 0; x < width; x++) {
                                var r = (int)Clamp (0, 255, (pixels[y * width + x + 0] + 32768) / 256);
                                var g = (int)Clamp (0, 255, (pixels[y * width + x + 1] + 32768) / 256);
                                var b = (int)Clamp (0, 255, (r + g) / 2);
                                bitmap.SetPixel (x, y, System.Drawing.Color.FromArgb (r, g, b));
                            }
                        }
                        bitmap.Save (name);
                        break;
                    }
                case PixelFormat.RG16ui: {
                        var bitmap = new Bitmap (width, height, System.Drawing.Imaging.PixelFormat.Format24bppRgb);
                        var pixels = (img as Image2D<ushort>).Pixels.ToArray ();
                        for (var y = 0; y < height; y++) {
                            for (var x = 0; x < width; x++) {
                                var r = (int)Clamp (0, 255, pixels[y * width + x + 0] / 256);
                                var g = (int)Clamp (0, 255, pixels[y * width + x + 1] / 256);
                                var b = (int)Clamp (0, 255, (r + g) / 2);
                                bitmap.SetPixel (x, y, System.Drawing.Color.FromArgb (r, g, b));
                            }
                        }
                        bitmap.Save (name);
                        break;
                    }
                case PixelFormat.RG32f: {
                        var bitmap = new Bitmap (width, height, System.Drawing.Imaging.PixelFormat.Format24bppRgb);
                        var pixels = (img as Image2D<float>).Pixels.ToArray ();
                        for (var y = 0; y < height; y++) {
                            for (var x = 0; x < width; x++) {
                                var r = (int)Clamp (0, 255, pixels[y * width + x + 0] * 255);
                                var g = (int)Clamp (0, 255, pixels[y * width + x + 1] * 255);
                                var b = (int)Clamp (0, 255, (r + g) / 2);
                                bitmap.SetPixel (x, y, System.Drawing.Color.FromArgb (r, g, b));
                            }
                        }
                        bitmap.Save (name);
                        break;
                    }
                case PixelFormat.RG32i: {
                        var bitmap = new Bitmap (width, height, System.Drawing.Imaging.PixelFormat.Format24bppRgb);
                        var pixels = (img as Image2D<int>).Pixels.ToArray ();
                        for (var y = 0; y < height; y++) {
                            for (var x = 0; x < width; x++) {
                                var r = (int)Clamp (0, 255, (pixels[y * width + x + 0] + 32768) / 256);
                                var g = (int)Clamp (0, 255, (pixels[y * width + x + 1] + 32768) / 256);
                                var b = (int)Clamp (0, 255, (r + g) / 2);
                                bitmap.SetPixel (x, y, System.Drawing.Color.FromArgb (r, g, b));
                            }
                        }
                        bitmap.Save (name);
                        break;
                    }
                case PixelFormat.RG32ui: {
                        var bitmap = new Bitmap (width, height, System.Drawing.Imaging.PixelFormat.Format24bppRgb);
                        var pixels = (img as Image2D<uint>).Pixels.ToArray ();
                        for (var y = 0; y < height; y++) {
                            for (var x = 0; x < width; x++) {
                                var r = (int)Clamp (0, 255, pixels[y * width + x + 0] / 256);
                                var g = (int)Clamp (0, 255, pixels[y * width + x + 1] / 256);
                                var b = (int)Clamp (0, 255, (r + g) / 2);
                                bitmap.SetPixel (x, y, System.Drawing.Color.FromArgb (r, g, b));
                            }
                        }
                        bitmap.Save (name);
                        break;
                    }
                case PixelFormat.RGB8: {
                        var bitmap = new Bitmap (width, height, System.Drawing.Imaging.PixelFormat.Format24bppRgb);
                        var pixels = (img as Image2D<float>).Pixels.ToArray ();
                        for (var y = 0; y < height; y++) {
                            for (var x = 0; x < width; x++) {
                                var r = (int)Clamp (0, 255, pixels[y * width + x + 0] * 255);
                                var g = (int)Clamp (0, 255, pixels[y * width + x + 1] * 255);
                                var b = (int)Clamp (0, 255, pixels[y * width + x + 2] * 255);
                                bitmap.SetPixel (x, y, System.Drawing.Color.FromArgb (r, g, b));
                            }
                        }
                        bitmap.Save (name);
                        break;
                    }
                case PixelFormat.RGB8i: {
                        var bitmap = new Bitmap (width, height, System.Drawing.Imaging.PixelFormat.Format24bppRgb);
                        var pixels = (img as Image2D<sbyte>).Pixels.ToArray ();
                        for (var y = 0; y < height; y++) {
                            for (var x = 0; x < width; x++) {
                                var r = (int)Clamp (0, 255, pixels[y * width + x + 0] + 128);
                                var g = (int)Clamp (0, 255, pixels[y * width + x + 1] + 128);
                                var b = (int)Clamp (0, 255, pixels[y * width + x + 2] + 128);
                                bitmap.SetPixel (x, y, System.Drawing.Color.FromArgb (r, g, b));
                            }
                        }
                        bitmap.Save (name);
                        break;
                    }
                case PixelFormat.RGB8ui: {
                        var bitmap = new Bitmap (width, height, System.Drawing.Imaging.PixelFormat.Format24bppRgb);
                        var pixels = (img as Image2D<byte>).Pixels.ToArray ();
                        for (var y = 0; y < height; y++) {
                            for (var x = 0; x < width; x++) {
                                var r = (int)Clamp (0, 255, pixels[y * width + x + 0]);
                                var g = (int)Clamp (0, 255, pixels[y * width + x + 1]);
                                var b = (int)Clamp (0, 255, pixels[y * width + x + 2]);
                                bitmap.SetPixel (x, y, System.Drawing.Color.FromArgb (r, g, b));
                            }
                        }
                        bitmap.Save (name);
                        break;
                    }
                case PixelFormat.RGB16: {
                        var bitmap = new Bitmap (width, height, System.Drawing.Imaging.PixelFormat.Format24bppRgb);
                        var pixels = (img as Image2D<float>).Pixels.ToArray ();
                        for (var y = 0; y < height; y++) {
                            for (var x = 0; x < width; x++) {
                                var r = (int)Clamp (0, 255, pixels[y * width + x + 0] * 256);
                                var g = (int)Clamp (0, 255, pixels[y * width + x + 1] * 256);
                                var b = (int)Clamp (0, 255, pixels[y * width + x + 2] * 256);
                                bitmap.SetPixel (x, y, System.Drawing.Color.FromArgb (r, g, b));
                            }
                        }
                        bitmap.Save (name);
                        break;
                    }
                case PixelFormat.RGB16f: {
                        var bitmap = new Bitmap (width, height, System.Drawing.Imaging.PixelFormat.Format24bppRgb);
                        var pixels = (img as Image2D<float>).Pixels.ToArray ();
                        for (var y = 0; y < height; y++) {
                            for (var x = 0; x < width; x++) {
                                var r = (int)Clamp (0, 255, pixels[y * width + x + 0] * 255);
                                var g = (int)Clamp (0, 255, pixels[y * width + x + 1] * 255);
                                var b = (int)Clamp (0, 255, pixels[y * width + x + 2] * 255);
                                bitmap.SetPixel (x, y, System.Drawing.Color.FromArgb (r, g, b));
                            }
                        }
                        bitmap.Save (name);
                        break;
                    }
                case PixelFormat.RGB16i: {
                        var bitmap = new Bitmap (width, height, System.Drawing.Imaging.PixelFormat.Format24bppRgb);
                        var pixels = (img as Image2D<short>).Pixels.ToArray ();
                        for (var y = 0; y < height; y++) {
                            for (var x = 0; x < width; x++) {
                                var r = (int)Clamp (0, 255, (pixels[y * width + x + 0] + 32768) / 256);
                                var g = (int)Clamp (0, 255, (pixels[y * width + x + 1] + 32768) / 256);
                                var b = (int)Clamp (0, 255, (pixels[y * width + x + 2] + 32768) / 256);
                                bitmap.SetPixel (x, y, System.Drawing.Color.FromArgb (r,g , b));
                            }
                        }
                        bitmap.Save (name);
                        break;
                    }
                case PixelFormat.RGB16ui: {
                        var bitmap = new Bitmap (width, height, System.Drawing.Imaging.PixelFormat.Format24bppRgb);
                        var pixels = (img as Image2D<ushort>).Pixels.ToArray ();
                        for (var y = 0; y < height; y++) {
                            for (var x = 0; x < width; x++) {
                                var r = (int)Clamp (0, 255, pixels[y * width + x + 0] / 256);
                                var g = (int)Clamp (0, 255, pixels[y * width + x + 1] / 256);
                                var b = (int)Clamp (0, 255, pixels[y * width + x + 2] / 256);
                                bitmap.SetPixel (x, y, System.Drawing.Color.FromArgb (r, g, b));
                            }
                        }
                        bitmap.Save (name);
                        break;
                    }
                case PixelFormat.RGB32f: {
                        var bitmap = new Bitmap (width, height, System.Drawing.Imaging.PixelFormat.Format24bppRgb);
                        var pixels = (img as Image2D<float>).Pixels.ToArray ();
                        for (var y = 0; y < height; y++) {
                            for (var x = 0; x < width; x++) {
                                var r = (int)Clamp (0, 255, pixels[y * width + x + 0] * 256);
                                var g = (int)Clamp (0, 255, pixels[y * width + x + 1] * 256);
                                var b = (int)Clamp (0, 255, pixels[y * width + x + 2] * 256);
                                bitmap.SetPixel (x, y, System.Drawing.Color.FromArgb (r, g, b));
                            }
                        }
                        bitmap.Save (name);
                        break;
                    }
                case PixelFormat.RGB32i: {
                        var bitmap = new Bitmap (width, height, System.Drawing.Imaging.PixelFormat.Format24bppRgb);
                        var pixels = (img as Image2D<int>).Pixels.ToArray ();
                        for (var y = 0; y < height; y++) {
                            for (var x = 0; x < width; x++) {
                                var r = (int)Clamp (0, 255, (pixels[y * width + x + 0] + 32768) / 256);
                                var g = (int)Clamp (0, 255, (pixels[y * width + x + 1] + 32768) / 256);
                                var b = (int)Clamp (0, 255, (pixels[y * width + x + 2] + 32768) / 256);
                                bitmap.SetPixel (x, y, System.Drawing.Color.FromArgb (r, g, b));
                            }
                        }
                        bitmap.Save (name);
                        break;
                    }
                case PixelFormat.RGB32ui: {
                        var bitmap = new Bitmap (width, height, System.Drawing.Imaging.PixelFormat.Format24bppRgb);
                        var pixels = (img as Image2D<uint>).Pixels.ToArray ();
                        for (var y = 0; y < height; y++) {
                            for (var x = 0; x < width; x++) {
                                var r = (int)Clamp (0, 255, pixels[y * width + x + 0] / 256);
                                var g = (int)Clamp (0, 255, pixels[y * width + x + 1] / 256);
                                var b = (int)Clamp (0, 255, pixels[y * width + x + 2] / 256);
                                bitmap.SetPixel (x, y, System.Drawing.Color.FromArgb (r, g, b));
                            }
                        }
                        bitmap.Save (name);
                        break;
                    }
                case PixelFormat.RGBA8: {
                        var bitmap = new Bitmap (width, height, System.Drawing.Imaging.PixelFormat.Format32bppArgb);
                        var pixels = (img as Image2D<float>).Pixels.ToArray ();
                        for (var y = 0; y < height; y++) {
                            for (var x = 0; x < width; x++) {
                                var r = (int)Clamp (0, 255, pixels[y * width + x + 0] * 255);
                                var g = (int)Clamp (0, 255, pixels[y * width + x + 1] * 255);
                                var b = (int)Clamp (0, 255, pixels[y * width + x + 2] * 255);
                                var a = (int)Clamp (0, 255, pixels[y * width + x + 3] * 255);
                                bitmap.SetPixel (x, y, System.Drawing.Color.FromArgb (r, g, b, a));
                            }
                        }
                        bitmap.Save (name);
                        break;
                    }
                case PixelFormat.RGBA8i: {
                        var bitmap = new Bitmap (width, height, System.Drawing.Imaging.PixelFormat.Format32bppArgb);
                        var pixels = (img as Image2D<sbyte>).Pixels.ToArray ();
                        for (var y = 0; y < height; y++) {
                            for (var x = 0; x < width; x++) {
                                var r = (int)Clamp (0, 255, pixels[y * width + x + 0] + 128);
                                var g = (int)Clamp (0, 255, pixels[y * width + x + 1] + 128);
                                var b = (int)Clamp (0, 255, pixels[y * width + x + 2] + 128);
                                var a = (int)Clamp (0, 255, pixels[y * width + x + 3] + 128);
                                bitmap.SetPixel (x, y, System.Drawing.Color.FromArgb (r, g, b, a));
                            }
                        }
                        bitmap.Save (name);
                        break;
                    }
                case PixelFormat.RGBA8ui: {
                        var bitmap = new Bitmap (width, height, System.Drawing.Imaging.PixelFormat.Format32bppArgb);
                        var pixels = (img as Image2D<byte>).Pixels.ToArray ();
                        for (var y = 0; y < height; y++) {
                            for (var x = 0; x < width; x++) {
                                var r = (int)Clamp (0, 255, pixels[y * width + x + 0]);
                                var g = (int)Clamp (0, 255, pixels[y * width + x + 1]);
                                var b = (int)Clamp (0, 255, pixels[y * width + x + 2]);
                                var a = (int)Clamp (0, 255, pixels[y * width + x + 3]);
                                bitmap.SetPixel (x, y, System.Drawing.Color.FromArgb (r, g, b, a));
                            }
                        }
                        bitmap.Save (name);
                        break;
                    }
                case PixelFormat.RGBA16: {
                        var bitmap = new Bitmap (width, height, System.Drawing.Imaging.PixelFormat.Format32bppArgb);
                        var pixels = (img as Image2D<float>).Pixels.ToArray ();
                        for (var y = 0; y < height; y++) {
                            for (var x = 0; x < width; x++) {
                                var r = (int)Clamp (0, 255, pixels[y * width + x + 0] * 255);
                                var g = (int)Clamp (0, 255, pixels[y * width + x + 1] * 255);
                                var b = (int)Clamp (0, 255, pixels[y * width + x + 2] * 255);
                                var a = (int)Clamp (0, 255, pixels[y * width + x + 3] * 255);
                                bitmap.SetPixel (x, y, System.Drawing.Color.FromArgb (r, g, b, a));
                            }
                        }
                        bitmap.Save (name);
                        break;
                    }
                case PixelFormat.RGBA16f: {
                        var bitmap = new Bitmap (width, height, System.Drawing.Imaging.PixelFormat.Format32bppArgb);
                        var pixels = (img as Image2D<float>).Pixels.ToArray ();
                        for (var y = 0; y < height; y++) {
                            for (var x = 0; x < width; x++) {
                                var r = (int)Clamp (0, 255, pixels[y * width + x + 0] * 255);
                                var g = (int)Clamp (0, 255, pixels[y * width + x + 1] * 255);
                                var b = (int)Clamp (0, 255, pixels[y * width + x + 2] * 255);
                                var a = (int)Clamp (0, 255, pixels[y * width + x + 3] * 255);
                                bitmap.SetPixel (x, y, System.Drawing.Color.FromArgb (r, g, b, a));
                            }
                        }
                        bitmap.Save (name);
                        break;
                    }
                case PixelFormat.RGBA16i: {
                        var bitmap = new Bitmap (width, height, System.Drawing.Imaging.PixelFormat.Format32bppArgb);
                        var pixels = (img as Image2D<short>).Pixels.ToArray ();
                        for (var y = 0; y < height; y++) {
                            for (var x = 0; x < width; x++) {
                                var r = (int)Clamp (0, 255, (pixels[y * width + x + 0] + 32768) / 256);
                                var g = (int)Clamp (0, 255, (pixels[y * width + x + 1] + 32768) / 256);
                                var b = (int)Clamp (0, 255, (pixels[y * width + x + 2] + 32768) / 256);
                                var a = (int)Clamp (0, 255, (pixels[y * width + x + 3] + 32768) / 256);
                                bitmap.SetPixel (x, y, System.Drawing.Color.FromArgb (r, g, b, a));
                            }
                        }
                        bitmap.Save (name);
                        break;
                    }
                case PixelFormat.RGBA16ui: {
                        var bitmap = new Bitmap (width, height, System.Drawing.Imaging.PixelFormat.Format32bppArgb);
                        var pixels = (img as Image2D<ushort>).Pixels.ToArray ();
                        for (var y = 0; y < height; y++) {
                            for (var x = 0; x < width; x++) {
                                var r = (int)Clamp (0, 255, pixels[y * width + x + 0] / 256);
                                var g = (int)Clamp (0, 255, pixels[y * width + x + 1] / 256);
                                var b = (int)Clamp (0, 255, pixels[y * width + x + 2] / 256);
                                var a = (int)Clamp (0, 255, pixels[y * width + x + 3] / 256);
                                bitmap.SetPixel (x, y, System.Drawing.Color.FromArgb (r, g, b, a));
                            }
                        }
                        bitmap.Save (name);
                        break;
                    }
                case PixelFormat.RGBA32f: {
                        var bitmap = new Bitmap (width, height, System.Drawing.Imaging.PixelFormat.Format32bppArgb);
                        var pixels = (img as Image2D<float>).Pixels.ToArray ();
                        for (var y = 0; y < height; y++) {
                            for (var x = 0; x < width; x++) {
                                var r = (int)Clamp (0, 255, pixels[y * width + x + 0] * 255);
                                var g = (int)Clamp (0, 255, pixels[y * width + x + 1] * 255);
                                var b = (int)Clamp (0, 255, pixels[y * width + x + 2] * 255);
                                var a = (int)Clamp (0, 255, pixels[y * width + x + 3] * 255);
                                bitmap.SetPixel (x, y, System.Drawing.Color.FromArgb (r, g, b, a));
                            }
                        }
                        bitmap.Save (name);
                        break;
                    }
                case PixelFormat.RGBA32i: {
                        var bitmap = new Bitmap (width, height, System.Drawing.Imaging.PixelFormat.Format32bppArgb);
                        var pixels = (img as Image2D<int>).Pixels.ToArray ();
                        for (var y = 0; y < height; y++) {
                            for (var x = 0; x < width; x++) {
                                var r = (int)Clamp (0, 255, (pixels[y * width + x + 0] + 32768) / 256);
                                var g = (int)Clamp (0, 255, (pixels[y * width + x + 1] + 32768) / 256);
                                var b = (int)Clamp (0, 255, (pixels[y * width + x + 2] + 32768) / 256);
                                var a = (int)Clamp (0, 255, (pixels[y * width + x + 3] + 32768) / 256);
                                bitmap.SetPixel (x, y, System.Drawing.Color.FromArgb (r, g, b, a));
                            }
                        }
                        bitmap.Save (name);
                        break;
                    }
                case PixelFormat.RGBA32ui: {
                        var bitmap = new Bitmap (width, height, System.Drawing.Imaging.PixelFormat.Format32bppArgb);
                        var pixels = (img as Image2D<uint>).Pixels.ToArray ();
                        for (var y = 0; y < height; y++) {
                            for (var x = 0; x < width; x++) {
                                var r = (int)Clamp (0, 255, pixels[y * width + x + 0] / 256);
                                var g = (int)Clamp (0, 255, pixels[y * width + x + 1] / 256);
                                var b = (int)Clamp (0, 255, pixels[y * width + x + 2] / 256);
                                var a = (int)Clamp (0, 255, pixels[y * width + x + 3] / 256);
                                bitmap.SetPixel (x, y, System.Drawing.Color.FromArgb (r, g, b, a));
                            }
                        }
                        bitmap.Save (name);
                        break;
                    }
                case PixelFormat.RGB9e5: {
                        var bitmap = new Bitmap (width, height, System.Drawing.Imaging.PixelFormat.Format32bppArgb);
                        var pixels = (img as Image2D<float>).Pixels.ToArray ();
                        for (var y = 0; y < height; y++) {
                            for (var x = 0; x < width; x++) {
                                var r = (int)Clamp (0, 255, pixels[y * width + x + 0] * 255);
                                var g = (int)Clamp (0, 255, pixels[y * width + x + 1] * 255);
                                var b = (int)Clamp (0, 255, pixels[y * width + x + 2] * 255);
                                var a = (int)Clamp (0, 255, pixels[y * width + x + 3] * 255);
                                bitmap.SetPixel (x, y, System.Drawing.Color.FromArgb (r, g, b, a));
                            }
                        }
                        bitmap.Save (name);
                        break;
                    }
                case PixelFormat.R11G11B10f: {
                        var bitmap = new Bitmap (width, height, System.Drawing.Imaging.PixelFormat.Format32bppArgb);
                        var pixels = (img as Image2D<float>).Pixels.ToArray ();
                        for (var y = 0; y < height; y++) {
                            for (var x = 0; x < width; x++) {
                                var r = (int)Clamp (0, 255, pixels[y * width + x + 0] * 255);
                                var g = (int)Clamp (0, 255, pixels[y * width + x + 1] * 255);
                                var b = (int)Clamp (0, 255, pixels[y * width + x + 2] * 255);
                                var a = (int)Clamp (0, 255, pixels[y * width + x + 3] * 255);
                                bitmap.SetPixel (x, y, System.Drawing.Color.FromArgb (r, g, b, a));
                            }
                        }
                        bitmap.Save (name);
                        break;
                    }
                case PixelFormat.RGB10A2: {
                        var bitmap = new Bitmap (width, height, System.Drawing.Imaging.PixelFormat.Format32bppArgb);
                        var pixels = (img as Image2D<float>).Pixels.ToArray ();
                        for (var y = 0; y < height; y++) {
                            for (var x = 0; x < width; x++) {
                                var r = (int)Clamp (0, 255, pixels[y * width + x + 0] * 255);
                                var g = (int)Clamp (0, 255, pixels[y * width + x + 1] * 255);
                                var b = (int)Clamp (0, 255, pixels[y * width + x + 2] * 255);
                                var a = (int)Clamp (0, 255, pixels[y * width + x + 3] * 255);
                                bitmap.SetPixel (x, y, System.Drawing.Color.FromArgb (r, g, b, a));
                            }
                        }
                        bitmap.Save (name);
                        break;
                    }
                case PixelFormat.RGB10A2ui: {
                        var bitmap = new Bitmap (width, height, System.Drawing.Imaging.PixelFormat.Format32bppArgb);
                        var pixels = (img as Image2D<ushort>).Pixels.ToArray ();
                        for (var y = 0; y < height; y++) {
                            for (var x = 0; x < width; x++) {
                                var r = (int)Clamp (0, 255, pixels[y * width + x + 0] >> 2);
                                var g = (int)Clamp (0, 255, pixels[y * width + x + 1] >> 2);
                                var b = (int)Clamp (0, 255, pixels[y * width + x + 2] >> 2);
                                var a = (int)Clamp (0, 255, pixels[y * width + x + 3] * 85);
                                bitmap.SetPixel (x, y, System.Drawing.Color.FromArgb (r, g, b, a));
                            }
                        }
                        bitmap.Save (name);
                        break;
                    }
                case PixelFormat.Depth: {
                        var bitmap = new Bitmap (width, height, System.Drawing.Imaging.PixelFormat.Format24bppRgb);
                        var pixels = (img as Image2D<float>).Pixels.ToArray ();
                        for (var y = 0; y < height; y++) {
                            for (var x = 0; x < width; x++) {
                                var r = (int)Clamp (0, 255, (1 - pixels[y * width + x]) * 255);
                                var g = (int)Clamp (0, 255, (1 - pixels[y * width + x]) * 255);
                                var b = (int)Clamp (0, 255, (1 - pixels[y * width + x]) * 255);
                                bitmap.SetPixel (x, y, System.Drawing.Color.FromArgb (r, g, b));
                            }
                        }
                        bitmap.Save (name);
                        break;
                    }
                default: throw new NotImplementedException ("Sorry, not implemented format=" + format);
            }
        }
    }
}
